//
// Created by vell on 2021/11/23.
//
#ifndef V_TIME_UTILS_H
#define V_TIME_UTILS_H

#include "VLog.h"
#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>
#include <unistd.h>

namespace VUtils {
    inline long long nowNs() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_REALTIME, &time);
        return (long long) time.tv_sec * 1000000000 + time.tv_nsec;
    }

    inline long long nowMs() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_REALTIME, &time);
        return (long long) time.tv_sec * 1000 + time.tv_nsec / 1000000;
    }

    inline double nowSec() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_REALTIME, &time);
        return time.tv_sec + time.tv_nsec / 1000000000.0;
    }

    inline double uptimeSec() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_MONOTONIC, &time);
        return time.tv_sec + time.tv_nsec / 1000000000.0;
    }

    inline void nowStr(std::string &str) {
        auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        char buffer[256];
        strftime(buffer, sizeof(buffer), "%Y-%m-%d_%H_%M_%S", std::localtime(&t));
        str = buffer;
    }

    inline void nowStr(std::string &str, const char *fmt) {
        auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        char buffer[256];
        strftime(buffer, sizeof(buffer), fmt, std::localtime(&t));
        str = buffer;
    }

    inline std::string nowStr() {
        auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        char buffer[256];
        strftime(buffer, sizeof(buffer), "%Y-%m-%d_%H_%M_%S", std::localtime(&t));
        return std::string(buffer);
    }

    inline std::string nowStr(const char *fmt) {
        auto t = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        char buffer[256];
        strftime(buffer, sizeof(buffer), fmt, std::localtime(&t));
        return std::string(buffer);
    }

    inline long long bootNs() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_BOOTTIME, &time);
        return time.tv_sec * 1000000000 + time.tv_nsec;
    }

    inline long long bootMs() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_BOOTTIME, &time);
        return (long long) time.tv_sec * 1000 + time.tv_nsec / 1000000;
    }

    inline double bootSec() {
        struct timespec time{0, 0};
        clock_gettime(CLOCK_BOOTTIME, &time);
        return time.tv_sec + time.tv_nsec / 1000000000.0;
    }

    inline void sleep(long ms) {
        usleep(ms * 1000);
    }

#define TS(name) long long t_##name = VUtils::nowNs();
#define TE(name) VLog("TIMER_" #name ": %0.3fms\n",(VUtils::nowNs() - t_##name) / 1000000.0);
}
#endif // V_TIME_UTILS_H
